package com.dynamic.idea.quick.develop.plugin.utils;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.dynamic.idea.quick.develop.plugin.entity.base02.*;
import com.dynamic.idea.quick.develop.plugin.entity.base02.model.ImportStruct;
import com.dynamic.idea.quick.develop.plugin.enums.GeneralPackageStructTypeEnums;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 生成规则工具类
 */
public class GeneralRuleUtils {

    // 项目名->项目结构映射
    private static Map<String, GeneralProjectStruct> PROJECT_NAME_2_PROJECT_STRUCT_MAP= new LinkedHashMap<>();

    // 项目名->规则的映射
    private static Map<String, GeneralRule> PROJECT_NAME_2_GENERAL_RULE_MAP= new LinkedHashMap<>();


    static {
        // 订单规则
//        GeneralRule orderGeneralRule = getOrderGeneralRule();
//
//        PROJECT_NAME_2_GENERAL_RULE_MAP.put("shendu-order-parent",orderGeneralRule);

        generateShenduStructTemplate();

    }

    public static void main(String[] args) {
        System.out.println(JSON.toJSONString(PROJECT_NAME_2_PROJECT_STRUCT_MAP,true));
//        System.out.println(JSON.toJSONString(PROJECT_NAME_2_GENERAL_RULE_MAP,true));
    }

    /**
     * 根据项目名得到规则
     * @param projectName
     * @return
     */
//    public static GeneralRule getRuleByProjectName(String projectName){
//        return PROJECT_NAME_2_GENERAL_RULE_MAP.get(projectName);
//    }

    public static boolean isConfigService(String projectName){
        return getProjectStructByName(projectName) !=null;
    }


    /**
     * 得到项目的结构规则列表
     * @param projectName
     * @return
     */
    public static List<GeneralRule> getProjectGeneralRuleList(String projectName,String className,String methodName) {
        //订单列表
        if (StringUtils.equals(projectName, "shendu-order-parent")) {
            return getGeneralRuleList("shendu-order-parent:order-stub", "cn.sdpjw.order.stub", "shendu-order-parent:order-service", "cn.sdpjw.order",
                    className, methodName);
        }
        if (StringUtils.equals(projectName, "shendu-operation-parent")) {
            return getGeneralRuleList("shendu-operation-parent:operation-stub", "cn.sdpjw.operation.stub",
                    "shendu-operation-parent:operation-service", "cn.sdpjw.operation",
                    className, methodName);
        }
        if (StringUtils.equals(projectName, "shendu-corp-parent")) {
            return getGeneralRuleList("shendu-corp-parent:corp-stub", "cn.sdpjw.corp.stub",
                    "shendu-corp-parent:corp-service", "cn.sdpjw.corp",
                    className, methodName);
        }
        if (StringUtils.equals(projectName, "shendu-connector-parent")) {
            return getGeneralRuleList("shendu-connector-parent:connector-stub", "cn.sdpjw.connector.stub",
                    "shendu-connector-parent:connector-service", "cn.sdpjw.connector",
                    className, methodName);
        }
        if (StringUtils.equals(projectName, "shendu-sso-parent")) {
            return getGeneralRuleList("shendu-sso-parent:sso-stub", "cn.sdpjw.sso.stub",
                    "shendu-sso-parent:sso-service", "cn.sdpjw.sso",
                    className, methodName);
        }
        if (StringUtils.equals(projectName, "shendu-broker-parent")) {
            return getGeneralRuleList("shendu-broker-parent:broker-stub", "cn.sdpjw.broker.stub",
                    "shendu-broker-parent:broker-service", "cn.sdpjw.broker",
                    className, methodName);
        }
        if (StringUtils.equals(projectName, "shendu-organization-parent")) {
            return getGeneralRuleList("shendu-organization-parent:organization-stub", "cn.sdpjw.organization.stub",
                    "shendu-organization-parent:organization-service", "cn.sdpjw.organization",
                    className, methodName);
        }
        if (StringUtils.equals(projectName, "shendu-draft-folder-parent")) {
            return getGeneralRuleList("shendu-draft-folder-parent:folder-stub", "cn.sdpjw.folder.stub",
                    "shendu-draft-folder-parent:folder-service", "cn.sdpjw.folder",
                    className, methodName);
        }

        if (StringUtils.equals(projectName, "shendu-statistics-parent")) {
            return getGeneralRuleList("shendu-statistics-parent:statistics-stub", "cn.sdpjw.statistics.stub",
                    "shendu-statistics-parent:statistics-service", "cn.sdpjw.statistics",
                    className, methodName);
        }

        if (StringUtils.equals(projectName, "shendu-discount-parent")) {
            return getGeneralRuleList("shendu-discount-parent:discount-stub", "cn.sdpjw.discount.stub",
                    "shendu-discount-parent:discount-service", "cn.sdpjw.discount",
                    className, methodName);
        }

        if (StringUtils.equals(projectName, "shendu-contract-parent")) {
            return getGeneralRuleList("shendu-contract-parent:contract-stub", "cn.sdpjw.contract.stub",
                    "shendu-contract-parent:contract-service", "cn.sdpjw.contract",
                    className, methodName);
        }

        if (StringUtils.equals(projectName, "shendu-activity-parent")) {
            return getGeneralRuleList("shendu-activity-parent:activity-stub", "cn.sdpjw.activity.stub",
                    "shendu-activity-parent:activity-service", "cn.sdpjw.activity",
                    className, methodName);
        }

        if (StringUtils.equals(projectName, "shendu-message-parent")) {
            return getGeneralRuleList("shendu-message-parent:message-stub", "cn.sdpjw.message.stub",
                    "shendu-message-parent:message-service", "cn.sdpjw.message",
                    className, methodName);
        }
        if (StringUtils.equals(projectName, "shendu-loyalty-parent")) {
            return getGeneralRuleList("shendu-loyalty-parent:loyalty-stub", "cn.sdpjw.loyalty.stub",
                    "shendu-loyalty-parent:loyalty-service", "cn.sdpjw.loyalty",
                    className, methodName);
        }



        return null;

    }

    private static List<GeneralRule> getGeneralRuleList(String stubProjectName,String stubPackageName,String serviceProjectName,String servicePackageName,String className,String methodName){
        //订单列表
        List<GeneralRule> generalRuleList=new ArrayList<>();

        // order-stub
        GeneralRule orderStubRule=getOrderProviderGeneralRule(stubProjectName,stubPackageName,"provider",
                "Provider",GeneralPackageStructTypeEnums.INTERFACE,className,methodName);
        if (orderStubRule!=null){
            generalRuleList.add(orderStubRule);
        }

        // 生成实体类 若存在则不生成
        GeneralRule entityGeneralRule=getOrderProviderGeneralRule(serviceProjectName,servicePackageName,"entity",
                "",GeneralPackageStructTypeEnums.CLASS,className,methodName);
        if (entityGeneralRule!=null){
            generalRuleList.add(entityGeneralRule);
        }

        // order-service-dao
        GeneralRule orderServiceDaoRule=getOrderProviderGeneralRule(serviceProjectName,servicePackageName,"dao",
                "Mapper",GeneralPackageStructTypeEnums.INTERFACE,className,methodName);
        if (orderServiceDaoRule!=null){
            //继承父类
            GeneralClassStruct classStruct = orderServiceDaoRule.getClassStruct();
            ImportStruct extendsImportStruct=new ImportStruct();
            // mybatis
            extendsImportStruct.setPackageName("com.baomidou.mybatisplus.core.mapper");
            extendsImportStruct.setClassName("BaseMapper");

            // 泛型
            List<ImportStruct> genericsClassStructList = new ArrayList<>();
            ImportStruct genericsImportStruct=new ImportStruct();

            // packageName
            genericsImportStruct.setPackageName(entityGeneralRule.getPackageStruct().getPackageFullName());
            genericsImportStruct.setClassName(className);

            genericsClassStructList.add(genericsImportStruct);
            extendsImportStruct.setGenericsClassStructList(genericsClassStructList);

            classStruct.setExtendsImportStruct(extendsImportStruct);
            generalRuleList.add(orderServiceDaoRule);
        }

        // MapperXml
        // order-service-mapperXml
//        GeneralRule orderMapperXmlRule=getOrderProviderGeneralRule("shendu-operation-parent:operation-service","","mapper",
//                "Mapper",GeneralPackageStructTypeEnums.MAPPER_XML,className,methodName);
//        if (orderMapperXmlRule!=null){
//                generalRuleList.add(orderMapperXmlRule);
//        }


        // order-service-service
        GeneralRule orderServiceServiceRule=getOrderProviderGeneralRule(serviceProjectName,servicePackageName,"service",
                "Service",GeneralPackageStructTypeEnums.INTERFACE,className,methodName);
        if (orderServiceServiceRule!=null){

            //继承父类
            GeneralClassStruct classStruct = orderServiceServiceRule.getClassStruct();
            ImportStruct extendsImportStruct=new ImportStruct();
            // mybatis
            extendsImportStruct.setPackageName("com.baomidou.mybatisplus.extension.service");
            extendsImportStruct.setClassName("IService");

            // 泛型
            List<ImportStruct> genericsClassStructList = new ArrayList<>();
            ImportStruct genericsImportStruct=new ImportStruct();

            // packageName
            genericsImportStruct.setPackageName(entityGeneralRule.getPackageStruct().getPackageFullName());
            genericsImportStruct.setClassName(className);

            genericsClassStructList.add(genericsImportStruct);
            extendsImportStruct.setGenericsClassStructList(genericsClassStructList);

            classStruct.setExtendsImportStruct(extendsImportStruct);

            generalRuleList.add(orderServiceServiceRule);
        }

        // order-service-serviceImpl
        GeneralRule orderServiceServiceImplRule=getOrderProviderGeneralRule(serviceProjectName,servicePackageName,"service.impl",
                "ServiceImpl",GeneralPackageStructTypeEnums.IMPLEMENTATION,className,methodName);
        if (orderServiceServiceImplRule!=null){
            // 实现接口
            orderServiceServiceImplRule.getClassStruct().setImplementsClassStruct(orderServiceServiceRule.getClassStruct());

            //继承父类
            GeneralClassStruct classStruct = orderServiceServiceImplRule.getClassStruct();
            ImportStruct extendsImportStruct=new ImportStruct();
            // mybatis
            extendsImportStruct.setPackageName("com.baomidou.mybatisplus.extension.service.impl");
            extendsImportStruct.setClassName("ServiceImpl");

            // 泛型
            List<ImportStruct> genericsClassStructList = new ArrayList<>();

            // 泛型1
            ImportStruct genericsImportStruct1=new ImportStruct();
            genericsImportStruct1.setPackageName(orderServiceDaoRule.getPackageStruct().getPackageFullName());
            genericsImportStruct1.setClassName(orderServiceDaoRule.getClassStruct().getClassFullName());
            genericsClassStructList.add(genericsImportStruct1);

            // 泛型2
            ImportStruct genericsImportStruct2=new ImportStruct();
            genericsImportStruct2.setPackageName(entityGeneralRule.getPackageStruct().getPackageFullName());
            genericsImportStruct2.setClassName(className);
            genericsClassStructList.add(genericsImportStruct2);

            extendsImportStruct.setGenericsClassStructList(genericsClassStructList);

            classStruct.setExtendsImportStruct(extendsImportStruct);

            //加注解
            List<ImportStruct> annotationImportStructList = new ArrayList<>();

            //注解1
            ImportStruct annotationImportStruct1=new ImportStruct();
            annotationImportStruct1.setPackageName("lombok.extern.slf4j");
            annotationImportStruct1.setClassName("Slf4j");
            annotationImportStructList.add(annotationImportStruct1);

            //注解2
            ImportStruct annotationImportStruct2=new ImportStruct();
            annotationImportStruct2.setPackageName("org.springframework.stereotype");
            annotationImportStruct2.setClassName("Service");
            annotationImportStructList.add(annotationImportStruct2);

            classStruct.setAnnotationImportStructList(annotationImportStructList);

            // 引用的嵌入子类
            GeneralClassStruct fieldGeneralClassStruct=new GeneralClassStruct();

            BeanUtil.copyProperties(orderServiceDaoRule.getClassStruct(),fieldGeneralClassStruct);

            // 是内嵌的
            fieldGeneralClassStruct.setInternalEmbedding(true);
            fieldGeneralClassStruct.setInternalEmbeddingFiledName("this.baseMapper");

            classStruct.setFieldGeneralClassStruct(fieldGeneralClassStruct);


            generalRuleList.add(orderServiceServiceImplRule);
        }

        // provider-service-serviceImpl
        GeneralRule orderProviderServiceImplRule=getOrderProviderGeneralRule(serviceProjectName,servicePackageName,"provider",
                "ProviderImpl",GeneralPackageStructTypeEnums.IMPLEMENTATION,className,methodName);
        if (orderProviderServiceImplRule!=null){
            // 实现接口
            orderProviderServiceImplRule.getClassStruct().setImplementsClassStruct(orderStubRule.getClassStruct());

            GeneralClassStruct classStruct = orderProviderServiceImplRule.getClassStruct();
            //加注解
            List<ImportStruct> annotationImportStructList = new ArrayList<>();

            //注解1
            ImportStruct annotationImportStruct1=new ImportStruct();
            annotationImportStruct1.setPackageName("lombok.extern.slf4j");
            annotationImportStruct1.setClassName("Slf4j");
            annotationImportStructList.add(annotationImportStruct1);

            //注解2
            ImportStruct annotationImportStruct2=new ImportStruct();
            annotationImportStruct2.setPackageName("org.apache.dubbo.config.annotation");
            annotationImportStruct2.setClassName("DubboService");
            annotationImportStructList.add(annotationImportStruct2);

            classStruct.setAnnotationImportStructList(annotationImportStructList);

            // 引用的service
            classStruct.setAnnotationImportStructList(annotationImportStructList);

            // 引用的嵌入子类
            GeneralClassStruct fieldGeneralClassStruct=new GeneralClassStruct();

            BeanUtil.copyProperties(orderServiceServiceRule.getClassStruct(),fieldGeneralClassStruct);

            // 是内嵌的
            fieldGeneralClassStruct.setInternalEmbedding(false);
            if (StringUtils.isNotBlank(fieldGeneralClassStruct.getClassFullName())){
                if (fieldGeneralClassStruct.getClassFullName().length()>1){
                    fieldGeneralClassStruct.setInternalEmbeddingFiledName(StringUtils.lowerCase(fieldGeneralClassStruct.getSimpleClassName().substring(0,1))+fieldGeneralClassStruct.getClassFullName().substring(1));
                }else {
                    fieldGeneralClassStruct.setInternalEmbeddingFiledName(StringUtils.lowerCase(fieldGeneralClassStruct.getSimpleClassName().substring(0,1)));
                }
            }

            // 加入注解
            List<String> internalAnnotationQualifiedNameList=new ArrayList<>();
            internalAnnotationQualifiedNameList.add("org.springframework.beans.factory.annotation.Autowired");
            fieldGeneralClassStruct.setInternalAnnotationQualifiedNameList(internalAnnotationQualifiedNameList);

            classStruct.setFieldGeneralClassStruct(fieldGeneralClassStruct);

            generalRuleList.add(orderProviderServiceImplRule);
        }


        // order-provider
//            GeneralRule orderServiceProviderImplRule=getOrderProviderGeneralRule("shendu-order-parent:order-service","cn.sdpjw.order","provider",
//                    "ProviderImpl",GeneralPackageStructTypeEnums.IMPLEMENTATION,className,methodName);
//            if (orderServiceProviderImplRule!=null){
//                generalRuleList.add(orderServiceProviderImplRule);
//            }
        return generalRuleList;
    }

    /**
     * 生成订单规则
     * @return
     */
    public static GeneralRule getOrderProviderGeneralRule(String childProjectName,String childProjectPackageName,String simplePackageName,
                                                          String classNameSuffix,GeneralPackageStructTypeEnums packageStructTypeEnums,String className,String methodName){
        GeneralRule rule=new GeneralRule();
        GeneralProjectStruct projectStruct =null;

        projectStruct = getProjectStructByName(childProjectName);
        if (projectStruct==null){
            System.out.println("projectStruct is null");
            return null;
        }
        projectStruct.setBaseJavaPackageName(StringUtils.trim(childProjectPackageName));

        rule.setProjectStruct(projectStruct);

        GeneralPackageStruct packageStruct = getCommonPackage(projectStruct, packageStructTypeEnums, StringUtils.trimToEmpty(simplePackageName));
        rule.setPackageStruct(packageStruct);

        // 类
        GeneralClassStruct classStruct=new GeneralClassStruct();
        classStruct.setBelongPackageStruct(packageStruct);
        classStruct.setClassNameSuffix(StringUtils.trimToEmpty(classNameSuffix));
        classStruct.setSimpleClassName(className);

        rule.setClassStruct(classStruct);

        // 方法
        GeneralMethodStruct methodStruct=new GeneralMethodStruct();
        methodStruct.setBelongClassStruct(classStruct);
        methodStruct.setName(methodName);

        rule.setMethodStruct(methodStruct);
        return rule;
    }


    /**
     * 根据项目名得到项目结构
     * @param projectName
     * @return
     */
    public static GeneralProjectStruct getProjectStructByName(String projectName){
        projectName=StringUtils.trim(projectName);
        return PROJECT_NAME_2_PROJECT_STRUCT_MAP.get(projectName);
    }

    /**
     * 生成深度的结构模板
     * @return
     */
    private static void generateShenduStructTemplate() {
        // 订单服务
        getCommonProject("shendu-order-parent:order-stub,order-service");
        // 核心服务
        getCommonProject("shendu-core-api");
    }

    private static GeneralPackageStruct getCommonPackage(GeneralProjectStruct projectStruct,GeneralPackageStructTypeEnums typeEnums,String packageName){
        if (StringUtils.isBlank(packageName)){
            return null;
        }
        List<GeneralPackageStruct> packageStructList=new ArrayList<>();
        // XML -> interface ->impl ->provider
        GeneralPackageStruct packageStruct=new GeneralPackageStruct();
        if (projectStruct!=null){
            packageStruct.setBelongProjectStruct(projectStruct);
        }
        packageStruct.setType(typeEnums.getValue());
        packageStruct.setPackageName(StringUtils.trim(packageName));
        return packageStruct;
    }

    /**
     * 通用的项目规则生成
     * shendu-order-parent:order-stub:a,order-service:b 结构
     * @param projectName
     * @return
     */
    private static GeneralProjectStruct getCommonProject(String projectName){
        return getCommonProject(null,projectName);
    }
    /**
     * 通用的项目规则生成
     * shendu-order-parent:order-stub:a,order-service:b 结构
     * @param projectName
     * @return
     */
    private static GeneralProjectStruct getCommonProject(GeneralProjectStruct parentProjectStruct,String projectName){
        if (StringUtils.isBlank(projectName)){
            return null;
        }
        projectName=StringUtils.trim(projectName);

        // 没有子项目
        String nowProjectName = StringUtils.trim(StringUtils.substringBefore(projectName, ":"));

        GeneralProjectStruct projectStruct=new GeneralProjectStruct();
        projectStruct.setName(nowProjectName);
        projectStruct.setParentProjectStruct(parentProjectStruct);

        // 当前项目的父项目的子项目
        if (parentProjectStruct!=null){

            Map<String, GeneralProjectStruct> childProjectStructMap = parentProjectStruct.getChildProjectStructMap();
            if (MapUtils.isEmpty(childProjectStructMap)){
                childProjectStructMap=new LinkedHashMap<>();
            }
            childProjectStructMap.put(projectStruct.getName(),projectStruct);
            parentProjectStruct.setChildProjectStructMap(childProjectStructMap);
        }

        // 当前项目的子项目
        String childProjectName = StringUtils.trim(StringUtils.substringAfter(projectName, ":"));
        String[] childProjectNameSplits = StringUtils.split(childProjectName, ",");
        if (ArrayUtils.isNotEmpty(childProjectNameSplits)){
            for(String split:childProjectNameSplits){
                //当前项目的子项目
                getCommonProject(projectStruct, split);
            }
        }
        PROJECT_NAME_2_PROJECT_STRUCT_MAP.put(projectStruct.getRoot2NowProjectName(),projectStruct);
        return projectStruct;
    }


}
